/*
 * @Author: xiaosihan 
 * @Date: 2021-04-11 16:20:16 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2021-11-07 16:30:49
 */
import _ from "lodash";
import * as THREE from "three";
import { BufferGeometry, Camera, Material, Scene, WebGLRenderer } from "three";
import Object3D from "../Object3D/Object3D";
import { Vector3, Vector3Call } from "../Object3D/type";

class Xrt_util {

    constructor() { }

    // 是否开发模式
    IS_DEV = process.env.NODE_ENV === "development";

    // 判断当前mesh对象是否显示出来了
    isVisible(mesh: Object3D): boolean {
        if (mesh.visible === false) {
            return false;
        } else if (mesh.visible === true && mesh.parent === null) {
            return true;
        } else if (mesh.visible === true && mesh.parent !== null) {
            return this.isVisible(mesh.parent);
        }
        return false;
    }

    // 获取一个 Object3d 对象的 根节点 Scene 对象
    getRoot(object3d?: Object3D): Object3D | THREE.Scene | undefined {
        if (!object3d) {
            return undefined
        } else if (object3d.parent) {
            return this.getRoot(object3d.parent);
        } else {
            return object3d;
        }
    }

    tempVector3 = new THREE.Vector3();

    // 顶点参数转换成顶点
    parseVector3(
        vector: Vector3 | Vector3Call = { x: 0, y: 0, z: 0 },
        renderer?: WebGLRenderer,
        scene?: Scene,
        camera?: Camera,
        object3d?: Object3D | null
    ): THREE.Vector3 {

        // 如果是空就默认是都是是0
        if (vector instanceof Function) {
            if (renderer && scene && camera && object3d) {
                return this.parseVector3(vector(renderer, scene, camera, object3d) as THREE.Vector3);
            }
        } else {

            const { x = 0, y = 0, z = 0 } = vector;
            this.tempVector3.set(x, y, z);
        }

        return this.tempVector3;
    }

    // 顶点参数转换成顶点
    parseScale(
        vector: Vector3 | Vector3Call = { x: 1, y: 1, z: 1 },
        renderer?: WebGLRenderer,
        scene?: Scene,
        camera?: Camera,
        object3d?: Object3D
    ): THREE.Vector3 {
        if (vector instanceof Function) {
            if (renderer && scene && camera && object3d) {
                return this.parseScale(vector(renderer, scene, camera, object3d) as THREE.Vector3);
            }
        } else {

            const { x = 1, y = 1, z = 1 } = vector;
            this.tempVector3.set(x, y, z);
        }
        return this.tempVector3;
    }

    tempEuler = new THREE.Euler();

    // 顶点参数转换成顶点
    parseEuler(
        vector: Vector3 | Vector3Call = { x: 0, y: 0, z: 0 },
        renderer?: WebGLRenderer,
        scene?: Scene,
        camera?: Camera,
        object3d?: Object3D
    ): THREE.Euler {

        if (vector instanceof Function) {
            if (renderer && scene && camera && object3d) {

                return this.parseEuler(vector(renderer, scene, camera, object3d) as THREE.Euler);

            }
        } else {

            const { x = 0, y = 0, z = 0 } = vector;

            this.tempEuler.set(x, y, z);
        }

        return this.tempEuler;
    }

    tempColor = new THREE.Color();

    // 颜色值转换成颜色对象
    parseColor(
        vector?: Vector3 | Vector3Call,
        renderer?: WebGLRenderer,
        scene?: Scene,
        camera?: Camera,
        group?: Object3D | null
    ) {
        // 如果是空就默认是都是是0
        if (!vector) {
            this.tempColor.set("#000000");
        } else if (vector instanceof Function) {
            if (renderer && scene && camera && group) {
                this.tempEuler.copy(vector(renderer, scene, camera, group) as THREE.Euler);
            }
        } else {
            this.tempColor
        }
        return this.tempColor;
    }

    // 是否是react 调试模式中
    isReactDev() {
        let react_devtool_dom = _.last(document.body.children);
        let zIndex = _.get(react_devtool_dom, ["style", "zIndex"]);
        return zIndex === "10000000";
    }

    // 任务队列
    isRuning: boolean = false;

    workList: Array<() => void> = [];

    // 时钟对象
    clock = new THREE.Clock();

    // 按照任务队列依次执行 性能优化
    /**
     *
     *
     * @param {() => void} [callback]
     * @param {boolean} [first=true] 需要优先执行
     * @returns
     * @memberof Xrt_util
     */
    requestAnimationFrame(callback?: () => void, first: boolean = false) {

        // 加入任务队列
        if (callback && !this.workList.includes(callback)) {
            if (first) {
                this.workList.splice(1, 0, callback); // 有限执行的任务回调
            } else {
                this.workList.push(callback);
            }
        }

        if (this.isRuning) {
            return;
        }

        // 没有任务需要执行的话就停止执行
        if (this.workList.length === 0) {
            this.isRuning = false;
            return;
        } else {
            this.isRuning = true;
        }

        requestAnimationFrame(() => {
            let callback = this.workList.splice(0, 1)[0];
            callback();
            this.isRuning = false;
            this.requestAnimationFrame();
        });
    }

}

const xrt_util = new Xrt_util();

export default xrt_util;

